package com.heatup.apt.api.service.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.baomidou.mybatisplus.plugins.Page;
import com.heatup.apt.api.controller.pay.util.PropertiesUtil;
import com.heatup.apt.api.service.CourseSignService;
import com.heatup.apt.api.service.TemplateSendService;
import com.heatup.apt.common.constants.ErrorCodeConstants;
import com.heatup.apt.common.constants.OrderContants;
import com.heatup.apt.common.dao.*;
import com.heatup.apt.common.util.*;
import com.heatup.apt.model.course.CourseTime;
import com.heatup.apt.model.order.*;
import com.heatup.apt.model.product.ServicePrice;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.heatup.apt.common.constants.CommonConstants;
import com.heatup.apt.common.dao.coach.CoachInfoMapper;
import com.heatup.apt.common.dao.user.UserInfoMapper;
import com.heatup.apt.model.api.ApiResultModel;
import com.heatup.apt.model.api.course.CourseCoachDetailResultModel;
import com.heatup.apt.model.coach.CoachInfo;
import com.heatup.apt.model.coach.CoachSigninLog;
import com.heatup.apt.model.course.CourseCoach;
import com.heatup.apt.model.course.CourseInfo;
import com.heatup.apt.model.course.CourseInfoModel;
import com.heatup.apt.model.course.CourseSchedule;
import com.heatup.apt.model.course.CourseSign;
import com.heatup.apt.model.user.UserInfo;

@Service
public class CourseSignServiceImpl implements CourseSignService {

    public static final Logger log = LoggerFactory.getLogger(CourseSignServiceImpl.class);
    public static final String USER_SIGNIN_URL_PRE = CommonPropertiesUtil.getString("user_signin_url").trim();

    public static final Integer QRCODE_MAX_OVERTIME = 30 ;
    public static final Integer QRCODE_MIN_OVERTIME = -30 ;

    @Autowired
    private CourseSignMapper courseSignMapper;
    @Autowired
    private CourseInfoMapper courseInfoMapper;
    @Autowired
    private CourseScheduleMapper courseScheduleMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private CoachInfoMapper coachInfoMapper;
    @Autowired
    private CourseCoachMapper courseCoachMapper;
    @Autowired
    private CoachSigninLogMapper coachSigninLogMapper;
    @Autowired
    private CourseSignOrderQueryModelMapper courseSignOrderQueryModelMapper;
    @Autowired
    private ServicePriceMapper servicePriceMapper;
    @Autowired
    private TemplateSendService templateSendService;

    public List<Map<String, Object>> queryUserCourseInfo(Integer userId, Integer courseId, Integer isclose, Integer orderId) {
        List<Map<String, Object>> map = courseSignMapper.queryUserCourseInfo(userId, courseId, isclose, orderId);
        return map;
    }

    /**
     * 销课
     *
     * @param storeId   门店地址
     * @param closeTime 销课时间
     * @return
     */
    @Override
    public Integer closeCourse(Integer id, Integer storeId, Date closeTime, Date startTime) {
        return courseSignMapper.closeCourse(id, storeId, closeTime, startTime);
    }

    /**
     * 销课
     *
     * <P>Date : 2016年10月21日 </P>
     *
     * @param num       课程顺序
     * @param id        签到ID
     * @param courseId  课程ID
     * @param storeId   门店ID
     * @param startTime 开始时间
     * @param closeTime 关闭时间
     * @return
     */
    @Override
    public int updateCancelCourse(String num, String id, String courseId,
                                  String storeId, String orderId, String startTime, String closeTime, Integer userId) throws Exception {

        Map<Object, Object> map = new HashMap<>();
        CourseSign cs = courseSignMapper.selectById(Integer.parseInt(id));
        if (cs == null) {
            throw new RuntimeException("没有对应的签到课程");
        }
        Integer num2 = cs.getCourseNumber();
        map.put("num", num2);
        map.put("orderId", orderId);
        int sign_less_num = orderInfoMapper.queryCourseSignLessNum(map);//已经签到了几节课
        OrderDetail orderDetail = orderDetailMapper.queryOrderDetailByOrderId(Integer.valueOf(orderId));
        if (num2.intValue() - 1 == sign_less_num) {
//            CourseCoachExample example = new CourseCoachExample();
//            example.or().andCourseIdEqualTo(Integer.valueOf(courseId));
//            List<CourseCoach> course_coach_list = courseCoachMapper.selectByExample(example);
            CourseCoach courseCoachDB = new CourseCoach();
            courseCoachDB.setCourseId(Integer.valueOf(courseId));
            EntityWrapper<CourseCoach> courseCoachEntityWrapper = new EntityWrapper<>(courseCoachDB);

            List<CourseCoach> course_coach_list = courseCoachMapper.selectList(courseCoachEntityWrapper);
            if (SetUtil.isNotNull(course_coach_list)) {
                map.put("coachId", course_coach_list.get(0).getCoachId());
            }
            map.put("storeId", storeId);
            map.put("startTime", startTime);
            map.put("closeTime", closeTime);
            map.put("id", Integer.valueOf(id));
            int count = orderInfoMapper.updateCancelCourse(map);

            map.clear();
            map.put("orderId", orderId);

            CourseInfo courseInfo = courseInfoMapper.selectById(Integer.valueOf(courseId));
            if (null != courseInfo) {
                /*int cs_count = courseInfo.getPeriods();*/
                int cs_count = (orderDetail.getCourseCount() != 0 ? orderDetail.getCourseCount() : courseInfo.getPeriods());
                if (cs_count != 0 && StringUtil.isEquals(num2, cs_count)) {
                    map.put("updatedBy", userId);
                    orderInfoMapper.updateOrderInfoStatus(map);
                }
            }
            return count;
        } else {
            return -1;
        }
    }

    /**
     *@Author: timo
     *@Date: 2018/3/27 11:19
     *@Description:
     * 教练端 - 添加日程管理
     *
     */
    @Override
    public ApiResultModel saveCourseSign(UserInfo userInfo, CourseSign courseSign) {
        ApiResultModel<Object> resultModel = new ApiResultModel<>();
        Map<String,Object> resultMap = new HashMap<>();
        boolean addSignStatus = Boolean.FALSE;

        // step 1 check user is coach
        // 校验
        CoachInfo coachInfo = coachInfoMapper.queryCoachByMobile(userInfo.getMobile());
        resultModel = checkSaveCourseSign(coachInfo, resultModel,courseSign);
        if(resultModel.getRet() != ApiResultModel.RET_SUCCESS) return resultModel;

        // 添加日程
        if(courseSign.getId() == null){
            // 判断一下是什么订单类型的
            OrderInfo orderInfo = orderInfoMapper.selectById(courseSign.getOrderId());
            if(orderInfo != null){
                if(OrderContants.OrderType.pt.getIndex() == orderInfo.getOrderType().intValue()){

                    courseSign.setCoachId(Long.valueOf(coachInfo.getId()));
                    courseSign.setUpdatedBy(userInfo.getId());
                    courseSign.setStoreId(coachInfo.getStoreId());
                    // 添加日程
                    addSignStatus = savePtCourseSign(courseSign);


                }else if(OrderContants.OrderType.physical_examination.getIndex() == orderInfo.getOrderType()
                        || OrderContants.OrderType.secret_experience.getIndex() == orderInfo.getOrderType()){

                    courseSign.setCoachId(Long.valueOf(coachInfo.getId()));
                    courseSign.setUpdatedBy(userInfo.getId());
                    courseSign.setUserId(orderInfo.getUserId());
                    // 添加日程
                    addSignStatus = savePlpeOrPlecCourseSign(courseSign);

                }else {
                    // 添加失败
                    resultModel.setRet(resultModel.RET_ERROR);
                    resultModel.setMsg("温馨提示：该日程或者该订单不存在！");
                    return resultModel;
                }
            }else{
                // 教练备忘录的添加
                courseSign.setCoachId(Long.valueOf(coachInfo.getId()));
                courseSign.setCreatedBy(userInfo.getId());
                addSignStatus = addCoachNote(courseSign);
            }



        }else{
            // 更新日程
            courseSign.setUpdatedTime(new Date());
            CourseSign courseSignOld = courseSignMapper.selectById(courseSign.getId());
            courseSignOld.setRemark(courseSign.getRemark());
            courseSignOld.setUpdatedTime(new Date());
            Date startTimeOld = courseSignOld.getStartTime();
            courseSignOld.setStartTime(courseSign.getStartTime());
            courseSignOld.setEndTime(courseSign.getEndTime());
            Integer signType = courseSign.getSignType() == null ? 1 : courseSign.getSignType();
            courseSignOld.setSignType(signType);
            addSignStatus = courseSignMapper.updateById(courseSignOld) > 0;
            OrderInfo orderInfo = orderInfoMapper.selectById(courseSignOld.getOrderId());

            if (orderInfo != null){
                if (orderInfo.getOrderType().intValue() == OrderContants.OrderType.pt.getIndex()){
                    // 变更时间
                    templateSendService.sendPtChangeTimeTemplateMsg(courseSignOld,startTimeOld);
                }else if(orderInfo.getOrderType().intValue() == OrderContants.OrderType.secret_experience.getIndex()
                        || orderInfo.getOrderType().intValue() == OrderContants.OrderType.physical_examination.getIndex()){
                    templateSendService.sendPtChangeTimeTemplateMsg(courseSignOld,startTimeOld);
                }
            }

        }

        if(addSignStatus){
            resultModel.setRet(resultModel.RET_SUCCESS);
            resultModel.setMsg("添加成功");
            resultMap.put("status",Boolean.TRUE);
            resultModel.setData(resultMap);
            return resultModel;
        }else{
            // 添加失败
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg("温馨提示：该私教课程日程已经添加完了，没有可添加的日程");
            return resultModel;
        }

    }

    public ApiResultModel checkSaveCourseSign(CoachInfo coachInfo, ApiResultModel resultModel, CourseSign courseSign){

        // 校验是不是教练
        if(coachInfo == null){
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg(ErrorCodeConstants.Code.COACH_NOT_MATCH.getMessage());
            resultModel.setErrorCode(ErrorCodeConstants.Code.COACH_NOT_MATCH.getCode());
            return resultModel;
        }

        // 不是私教教练没有权限添加课程日程
        if(courseSign.getSignType() == null || courseSign.getSignType() == 1){
            if(coachInfo.getIsPrivate() != 1){
                resultModel.setRet(resultModel.RET_ERROR);
                resultModel.setMsg(ErrorCodeConstants.Code.NOT_HAS_PERMISSIONS.getMessage());
                resultModel.setErrorCode(ErrorCodeConstants.Code.NOT_HAS_PERMISSIONS.getCode());
                return resultModel;
            }
        }

        // 校验是否同一时间段内存在重复的日程
        if(courseSign.getSignType() == null){
            if(checkScheduleRepeat(courseSign.getOrderId(),courseSign.getStartTime(),courseSign.getEndTime(), courseSign.getId())){
                resultModel.setRet(resultModel.RET_ERROR);
                resultModel.setMsg(ErrorCodeConstants.Code.COURSE_TIME_TO_REPEAT.getMessage());
                resultModel.setErrorCode(ErrorCodeConstants.Code.COURSE_TIME_TO_REPEAT.getCode());
                return resultModel;
            }
        }

        if(courseSign.getSignType() != null && courseSign.getSignType() == 2){
            if(StringUtil.isEmpty(courseSign.getStartTime())){
                resultModel.setRet(resultModel.RET_ERROR);
                resultModel.setMsg("开始时间不能为空");
                return resultModel;
            }

            if(StringUtil.isEmpty(courseSign.getEndTime())){
                resultModel.setRet(resultModel.RET_ERROR);
                resultModel.setMsg("结束时间不能为空");
                return resultModel;
            }
        }

        resultModel.setRet(resultModel.RET_SUCCESS);
        return resultModel;

    }

    /**
     *@Author: timo
     *@Date: 2018/4/11 09:57
     *@Description:
     * 查询教练的日程
     * 1.团课  每当团课一建成 就会在对应的日期中插入日程数据
     * 2.私教  只有在教练预约学员之后才会插入 日程数据
     * 3.训练营 每当训练营一建成 就会在对应的日期中插入日程数据
     * 4.体测 只有在教练预约学员之后才会插入 日程数据
     * 5.体验 只有在教练预约学员之后才会插入 日程数据
     *
     *
     * 查询用户：
     * 主管教练查询下面教练的客户 和日程
     * 教练自己查询自己的上课信息
     */
    @Override
    public ApiResultModel queryCoachCourseSignList(UserInfo userInfo, Date queryDate, Integer sonCoachId, Integer isChiefCoach) {
        ApiResultModel<Object> resultModel = new ApiResultModel<>();
        Map<String,Object> paramMap = new HashMap<>();

        CoachInfo coachInfo = null;

        // sonCoachId 大于 0 的时候就表示 是主教练查询团队教练的课程信息
        if(sonCoachId > 0){
            coachInfo = coachInfoMapper.selectById(sonCoachId);
        }else {
            coachInfo = coachInfoMapper.queryCoachByMobile(userInfo.getMobile());
        }
        if(coachInfo == null){
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg(ErrorCodeConstants.Code.COACH_NOT_MATCH.getMessage());
            resultModel.setErrorCode(ErrorCodeConstants.Code.COACH_NOT_MATCH.getCode());
            return resultModel;
        }

        paramMap.put("coachId",coachInfo.getId());
        paramMap.put("startTime",queryDate);

        List<CourseSignOrderQueryModel> courseSignOrderList = courseSignOrderQueryModelMapper.queryCoachCourseSignList(paramMap);
        paramMap.clear();
        paramMap.put("courseSignList",courseSignOrderList);
        paramMap.put("isChiefCoach",isChiefCoach);
        resultModel.setRet(resultModel.RET_SUCCESS);
        resultModel.setData(paramMap);
        return resultModel;
    }

    /**
     *@Author: timo
     *@Date: 2018/3/29 15:33
     *@Description:
     * 查询日程详情
     *
     */
    @Override
    public ApiResultModel queryCourseSignDetail(UserInfo userInfo, Integer courseSignId, Integer orderType) {
        ApiResultModel<Object> resultModel = new ApiResultModel<>();
        CourseSignOrderQueryModel model = null;
        Map<String, Object> resultMap = new HashMap<>();
        // 分类型来获取
        if (OrderContants.OrderType.team_course.getIndex() == orderType) {
            model = queryTeamCourseSignDetail(courseSignId);

        } else if (OrderContants.OrderType.pt.getIndex() == orderType) {
            model = queryPtCourseSignDetail(courseSignId);

        } else if (OrderContants.OrderType.fun_camp.getIndex() == orderType) {
            model = queryCampCourseSignDetail(courseSignId);

        } else if (OrderContants.OrderType.physical_examination.getIndex() == orderType
                || OrderContants.OrderType.secret_experience.getIndex() == orderType) {
            model = queryPlpeOrPlecCourseSignDetail(courseSignId);

        } else {
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg("订单类型错误！");
            return resultModel;

        }
        if (model == null) {
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg("该日程不存在！");
            return resultModel;
        }

        // 获取签到二维码
        model.setSignQrCode(getSignQrCode(model, orderType));

        // 获取签到二维码状态
        model.setSignCodeStatus(getSignQRCodeStatus(model.getStartTime(), model.getEndTime(), model.getCourseType()));

        resultMap.put("courseSignDetail", model);
        resultModel.setData(resultMap);
        resultModel.setRet(resultModel.RET_SUCCESS);
        return resultModel;
    }

    public String getSignQrCode(CourseSignOrderQueryModel model, Integer orderType){

        Date startTime = DateUtil.addMinites(model.getStartTime(), -30);
        Date endTime = DateUtil.addMinites(model.getEndTime(), 30);
        Date nowTime = new Date();

        // 如果未到该日程的开始时间就不显示签到二维码 提前三十分钟才显示
        if (!startTime.before(nowTime)) return null;

        // 二维码延长半小时 这里只是限制了团课和训练营的 其余的不做限制
        if (endTime.before(nowTime) && OrderContants.OrderType.team_course.getIndex() == orderType.intValue()
                || endTime.before(nowTime) && OrderContants.OrderType.fun_camp.getIndex() == orderType.intValue()) return null;

        // 这边临时生成一个签到的二维码
        String url = String.valueOf(PropertiesUtil.get("user_sign_in_url")).trim();
        url = url.replace("{0}",model.getCourseSignId()+"")
                .replace("{1}",(model.getOrderId() == null ? 0 : model.getOrderId()) +"")
                .replace("{2}",model.getCourseId()+"");
        log.info("user_sign_url:"+url);
        url = "data:image/png;base64," + QRCodeUtil.createQRCodeToBAS64String(url,200,200);

        return url;
    }

    /**
     *@Author: timo
     *@Date: 2018/3/29 22:23
     *@Description:
     * 日程的取消
     * 1.私教的日程取消 直接将日程中的教练置为null 让该日程回到客户管理中
     * 2.体测体验的取消  直接将日程删除 推到客户管理中
     *
     */
    @Override
    public ApiResultModel cancelCourseSign(UserInfo userInfo, Integer courseSignId, Integer courseType, Integer coachId) {
        log.info("============= cancelCourseSign start ============");
        ApiResultModel<Object> resultModel = new ApiResultModel<>();
        Map<String,Object> resultMap = new HashMap<>();
        // step 1 check user is coach
        CoachInfo coachInfo = coachInfoMapper.queryCoachByMobile(userInfo.getMobile());
        if(coachInfo == null){
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg(ErrorCodeConstants.Code.COACH_NOT_MATCH.getMessage());
            resultModel.setErrorCode(ErrorCodeConstants.Code.COACH_NOT_MATCH.getCode());
            return resultModel;
        }

        CourseSign courseSign = courseSignMapper.selectById(courseSignId);
        Date startDate = courseSign.getStartTime();
        Date endDate = courseSign.getEndTime();
        long coachIdOld = courseSign.getCoachId();
        if(courseSign == null){
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg("该日程不存在");
            return resultModel;
        }

        if(coachIdOld != coachInfo.getId()){
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg("温馨提示：不是您的日程您不能取消");
            return resultModel;
        }

        // step 2 判断是什么样子的日程
        if(courseSign.getSignType() == 1){
            if(OrderContants.OrderType.pt.getIndex() == courseType){
                courseSign.setStartTime(null);
                courseSign.setEndTime(null);
                courseSign.setCoachId(null);

            }else if (OrderContants.OrderType.physical_examination.getIndex() == courseType
                    || OrderContants.OrderType.secret_experience.getIndex() == courseType){
                courseSign.setStartTime(null);
                courseSign.setEndTime(null);
                courseSign.setCoachId(null);
                courseSign.setStatus(2); // 表示删除
            }
        }else{
            // 备忘录的
            courseSign.setStartTime(null);
            courseSign.setEndTime(null);
            courseSign.setSignType(3);

        }

        int updateCount = courseSignMapper.updateById(courseSign);
        if(updateCount > 0){
            resultModel.setRet(resultModel.RET_SUCCESS);
            resultModel.setMsg("取消成功！");

            // 发送模板消息
            if(OrderContants.OrderType.pt.getIndex() == courseType
                    || OrderContants.OrderType.physical_examination.getIndex() == courseType
                    || OrderContants.OrderType.secret_experience.getIndex() == courseType){
                courseSign.setStartTime(startDate);
                courseSign.setEndTime(endDate);
                courseSign.setCoachId(coachIdOld);
                templateSendService.sendPtCanCelCourseSignTemplateMsg(courseSign);
            }
            log.info("============= cancelCourseSign end ============");
            return resultModel;
        }else{
            resultModel.setRet(resultModel.RET_SUCCESS);
            resultModel.setMsg("温馨提示：取消失败，请联系管理人员！");
            return resultModel;
        }
    }

    @Override
    public ApiResultModel queryCoachNoteList(UserInfo userInfo, Integer pageIndex, Integer pageSize) {
        ApiResultModel<Object> apiResultModel = new ApiResultModel<>();
        Map<String,Object> paramMap = new HashMap<>();
        CoachInfo coachInfo = coachInfoMapper.queryCoachByMobile(userInfo.getMobile());
        if (coachInfo == null){
            apiResultModel.setRet(apiResultModel.RET_ERROR);
            apiResultModel.setMsg(ErrorCodeConstants.Code.COACH_NOT_MATCH.getMessage());
            apiResultModel.setErrorCode(ErrorCodeConstants.Code.COACH_NOT_MATCH.getCode());
            return apiResultModel;
        }
        paramMap.put("coachId",coachInfo.getId());
        Page<CourseSign> page = new Page<>(pageIndex,pageSize);

        page.setRecords(courseSignMapper.queryCoachNoteListPage(page,paramMap));
        paramMap.put("noteList",page.getRecords());
        paramMap.put("pageCount",page.getPages());
        paramMap.put("totalCount",page.getTotal());
        apiResultModel.setRet(apiResultModel.RET_SUCCESS);
        apiResultModel.setData(paramMap);
        return apiResultModel;
    }

    @Override
    public ApiResultModel delCourseSign(UserInfo userInfo, CoachInfo coachInfo, Integer courseSignId) {
        ApiResultModel<Object> apiResultModel = new ApiResultModel<>();
        Map<String,Object> paramMap = new HashMap<>();

        CourseSign courseSign = new CourseSign();
        courseSign.setCoachId(Long.valueOf(coachInfo.getId()));
        courseSign.setId(courseSignId);
        courseSign = courseSignMapper.selectOne(courseSign);
        if (courseSign != null){
            courseSign.setStatus(2);
            int updateCount = courseSignMapper.updateById(courseSign);
            if(updateCount > 0){
                apiResultModel.setRet(apiResultModel.RET_SUCCESS);
                apiResultModel.setMsg("删除成功");
                return apiResultModel;
            }else {
                apiResultModel.setRet(apiResultModel.RET_ERROR);
                apiResultModel.setMsg("删除失败");
                return apiResultModel;
            }

        }else{
            apiResultModel.setRet(apiResultModel.RET_ERROR);
            apiResultModel.setMsg("该备忘录不存在");
        }
        return apiResultModel;
    }

    @Override
    public Map<String, Object> queryCoachPrivateCourseSignList(Map<String, Object> paramsMap) {
        Integer pageIndex = (Integer) paramsMap.get("pageIndexs");
        pageIndex = pageIndex + 1;
        Integer pageSize = (Integer) paramsMap.get("pageSize");
        Map<String,Object> resultMap = new HashMap<>();
        Page<OrderPrivateUser> page = new Page<>(pageIndex,pageSize);
        page.setRecords(courseSignMapper.queryCoachPrivateCourseSignList(page,paramsMap));
        resultMap.put("list",page.getRecords());
        resultMap.put("count",page.getTotal());
        return resultMap;
    }

    @Override
    public boolean userSignUpdateCourseSign(Integer courseSignId, Integer personCount) {
        CourseSign courseSign = courseSignMapper.selectById(courseSignId);
        courseSign.setIsclose("1");
        courseSign.setUpdatedTime(new Date());
        courseSign.setCloseTime(new Date());
        personCount = personCount + (courseSign.getSignPersonCount() == null ? 1 : courseSign.getSignPersonCount());
        courseSign.setSignPersonCount(personCount);
        return courseSignMapper.updateById(courseSign) > 0;
    }

    @Override
    public ApiResultModel queryCoachNoteDetail(CoachInfo coachInfo, Integer courseSignId) {
        ApiResultModel<Object> resultModel = new ApiResultModel<>();
        CourseSign courseSign = new CourseSign();
        courseSign.setCoachId(Long.valueOf(coachInfo.getId()));
        courseSign.setId(courseSignId);

        courseSign = courseSignMapper.selectOne(courseSign);

        if(courseSign == null){
            resultModel.setRet(resultModel.RET_ERROR);
            resultModel.setMsg("该备忘录不存在！");
            return resultModel;
        }

        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("courseSign",courseSign);
        resultModel.setData(resultMap);
        resultModel.setRet(resultModel.RET_SUCCESS);
        return resultModel;
    }


    // 团课
    public CourseSignOrderQueryModel queryTeamCourseSignDetail(Integer courseSignId){
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("courseSignId",courseSignId);
        CourseSignOrderQueryModel model = courseSignOrderQueryModelMapper.queryTeamCourseSignDetail(paramMap);
        return model;
    }

    // 私教
    public CourseSignOrderQueryModel queryPtCourseSignDetail(Integer courseSignId){
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("courseSignId",courseSignId);
        CourseSignOrderQueryModel model = courseSignOrderQueryModelMapper.queryPtCourseSignDetail(paramMap);
        return model;
    }

    // 训练营
    public CourseSignOrderQueryModel queryCampCourseSignDetail(Integer courseSignId){
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("courseSignId",courseSignId);
        CourseSignOrderQueryModel model = courseSignOrderQueryModelMapper.queryCampCourseSignDetail(paramMap);
        return model;
    }

    // 体测体验
    public CourseSignOrderQueryModel queryPlpeOrPlecCourseSignDetail(Integer courseSignId){
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("courseSignId",courseSignId);
        CourseSignOrderQueryModel model = courseSignOrderQueryModelMapper.queryPlpeOrPlecCourseSignDetail(paramMap);
        return model;
    }
    /**
     * 教练 课程详情
     *
     * @param courseId 课程ID
     * @param mobile   教练手机
     * @return 课程详情
     */
    @Override
    public Map<String, Object> chaxuCoachCourseInfoById(Integer courseId, String mobile) throws Exception {

        Map<String, Object> resultMap = new HashMap<>();
        CourseCoachDetailResultModel course = courseSignMapper.queryCoachCourseInfo(courseId, mobile);
        if (course != null) {
            //查看课程是否即将开始
//            Date startTime = course.getStartTime();
//            Date endTime = course.getEndTime();

            CourseTime courseTime = courseInfoMapper.queryCourseStartTimeByCourseId(courseId);
            Date startTime = courseTime.getCourseStartTime();
            if (course.getCourseType().equals("3")) {
                String[] campClassTime = courseTime.getCampClassTime().split(",");
                startTime = DateUtil.parseUtilDate(campClassTime[courseTime.getWeek() - 1], DateUtil.FMT_DATE_YYYYMMDDHHMM);
            }
            Date nowTime = new Date();
            if (startTime != null) {
                String url;
                //检查二维码是否不存在
                if (StringUtils.isBlank(course.getSignInQrcodeUrl())) {
                    //不存在 需要生成
                    url = USER_SIGNIN_URL_PRE.replace("${courseId}", course.getCourseId().toString());
                    log.info("跳转URL ----------------->>> " + url);
                    //转换短链接创建二维码并上传到OSS返回URL
                    url = QRCodeUtil.createSignInQRCode(url);
                    course.setHeadImg(url);//跳转链接
                    //更新到DB
                    CourseInfo courseInfo = new CourseInfo();
                    courseInfo.setId(course.getCourseId());
                    courseInfo.setSignInQrcodeUrl(url);
                    courseInfo.setVersion(course.getVersion());
                    courseInfoMapper.updateSelectiveById(courseInfo);//updateByPrimaryKeyAndVersionSelective(courseInfo);
                } else {
                    //存在 直接从DB取
                    url = course.getSignInQrcodeUrl();
                }
                if (course.getCourseType().equals("1")) {//团课
                    //课程开始前20分钟 || 课程结束300分钟(5小时)内
                    if (nowTime.after(DateUtils.addMinutes(startTime, -20)) && DateUtils.addMinutes(startTime, 400).after(nowTime)) {
                        course.setSignInQrcodeUrl(url);//设置签到url返回
                    } else {
                        course.setSignInQrcodeUrl("");//不显示二维码
                    }
                } else if (course.getCourseType().equals("3")) {//檬营
                    CourseSchedule courseSchedule = courseScheduleMapper.selectByCourseId(courseId);
                    if (courseSchedule != null && StringUtils.isNotBlank(courseSchedule.getWeekly())
                            && courseSchedule.getWeekly().equals("1")
                            && course.getCurrentCount() >= course.getMinCount()) {//檬营成营和开启签到才返回二维码
                        course.setSignInQrcodeUrl(url);//设置签到url返回
                    } else {
                        course.setSignInQrcodeUrl("");//不显示二维码
                    }
                    resultMap.put("dateNow", new Date());
                }
            }
            if (course.getCourseType().equals("1") && course.getLeftDays() >= 0) {
                resultMap.put("signInCount", courseSignMapper.queryCoachCourseSignInCount(courseId, 1, mobile));
            } else if (course.getCourseType().equals("3")) {
                if (course.getCourseNumber() != null) {
                    int courseNumber = course.getCourseNumber();
                    resultMap.put("signInCount", courseSignMapper.queryCoachCourseSignInCount(courseId, courseNumber, mobile));
                }
            }
        }

        resultMap.put("course", course);
        return resultMap;
    }

    /**
     * 用户签到
     *
     * @param courseId 课程ID
     * @param openId   用户openId
     * @return
     * @throws Exception
     */
    @Override
    public ApiResultModel courseCoachUserSign(Integer courseId, String openId) throws Exception {
        log.info("用户签到 API----->> courseId " + courseId + " openId " + openId);
        ApiResultModel apiResultModel = new ApiResultModel();
        Map<String, Object> resultMap = new HashMap<>();
        boolean result = false;
        if (courseId == null || StringUtils.isBlank(openId)) {
            apiResultModel.setMsg("用户课程ID或openId不正确!不可签到");
            log.info("用户课程ID或openId不正确!不可签到");
        } else {
            //查询课程详情
            CourseInfoModel courseInfo = courseInfoMapper.queryCourseByCourseId(courseId);
            UserInfo userInfo = userInfoMapper.selectByOpenid(openId);

            //查询用户是否已经购买当前订单
            boolean isBuyThisOrder = orderInfoMapper.queryOrderByUserIdAndCourseId(userInfo.getId(), courseId) > 0;
            if (!isBuyThisOrder) {
                apiResultModel.setMsg("当前用户并没有购买此订单!不可签到");
                log.info("当前用户" + userInfo.getId() + "nickname " + userInfo.getNickName() + "并没有购买此订单!不可签到");
            } else {

                CourseSign courseSign = new CourseSign();
                courseSign.setCourseId(courseId);
                CourseSchedule courseSchedule = courseScheduleMapper.selectByCourseId(courseId);
                if (courseSchedule.getWeek() != null && courseInfo.getCourseType().equals("3")) {//檬营需要添加签到课时时序
                    courseSign.setCourseNumber(courseSchedule.getWeek());
                } else {//团课只有1节需要签到
                    courseSign.setCourseNumber(1);
                }
                courseSign.setUserId(userInfo.getId());
                courseSign.setIsclose(CommonConstants.NO);
                CourseSign courseSignDB = courseSignMapper.selectByCourseSign(courseSign);
                log.info("courseSignDB " + courseInfo.toString());
                if (courseSignDB != null) {
                    //已经签到过,不再重复插入数据,直接返回成功
                    result = true;
                } else {
                    courseSign.setCreatedBy(userInfo.getId());
                    courseSign.setCreatedTime(new Date());
                    result = courseSignMapper.insertSelective(courseSign) > 0;
                    log.info("用户签到 ---> " + userInfo.getId() + userInfo.getNickName() + userInfo.getMobile() + " 课程ID-> " + courseId + "result " + result);
                }
            }
        }

        resultMap.put("success", result);
        apiResultModel.setData(resultMap);
        return apiResultModel;
    }

    /**
     * 用户签到详情
     *
     * @param courseId 课程ID
     * @param userId   用户Id
     * @return
     * @throws Exception
     */
    @Override
    public ApiResultModel courseUserSignInfo(Integer courseId, Integer userId) throws Exception {
        log.info("用户签到 API----->> courseId " + courseId + " userId " + userId);
        ApiResultModel apiResultModel = new ApiResultModel();
        Map<String, Object> resultMap = new HashMap<>();
        boolean result = false;
        if (courseId == null || userId == null) {
            apiResultModel.setMsg("用户课程ID或userId不正确!不可签到");
            log.info("用户课程ID或userId不正确!不可签到");
        } else {
            //查询课程详情
            CourseInfoModel courseInfoDB = courseInfoMapper.queryCourseByCourseId(courseId);
            log.info("courseInfoDB " + courseInfoDB.toString());
            CourseInfoModel courseInfo = new CourseInfoModel();
            courseInfo.setId(courseInfoDB.getId());
            courseInfo.setCourseType(courseInfoDB.getCourseType());
            courseInfo.setTitle(courseInfoDB.getTitle());
            courseInfo.setCurrentCount(courseInfoDB.getCurrentCount());
            if (courseInfoDB.getStartTime() != null) {
                courseInfo.setStartTimeStr(com.heatup.apt.common.util.DateUtils.format(courseInfoDB.getStartTime(), com.heatup.apt.common.util.DateUtils.datePattern));
            }
            courseInfo.setHourMin(courseInfoDB.getHourMin());
            courseInfo.setIsVipUsed(courseInfoDB.getIsVipUsed());
            courseInfo.setStoreName(courseInfoDB.getStoreName());
            resultMap.put("course", courseInfo);

            UserInfo userInfoDB = userInfoMapper.selectById(userId);
            UserInfo userInfo = new UserInfo();
            userInfo.setId(userInfoDB.getId());
            userInfo.setHeadImg(userInfoDB.getHeadImg());
            userInfo.setNickName(userInfoDB.getNickName());
            userInfo.setLevel(userInfoDB.getLevel());
            resultMap.put("user", userInfo);

            //查询用户是否已经购买当前订单
            boolean isBuyThisOrder = false;
            //查询订单ID 人数 类型
            List<OrderUserInfo> orderUserInfoList = orderInfoMapper.queryOrderInfoByCourseIdAndUserId(userInfoDB.getId(), courseId);
            if (orderUserInfoList == null || orderUserInfoList.size() == 0) {
                apiResultModel.setMsg("当前用户并没有购买此订单!");
                log.info("当前用户" + userInfoDB.getId() + " nickname " + userInfoDB.getNickName() + "并没有购买此订单!");
            } else {
                isBuyThisOrder = true;
                resultMap.put("orderList", orderUserInfoList);
                result = true;
            }
            resultMap.put("isBuyThisOrder", isBuyThisOrder);
        }
        resultMap.put("success", result);
        apiResultModel.setData(resultMap);
        return apiResultModel;
    }

    /**
     * 教练 檬营开启/关闭签到
     *
     * @param courseId     课程ID
     * @param courseNumber 课时时序
     * @param type         签到类型 1开启 0关闭
     * @return
     */
    @Override
    public boolean campCourseSignIn(Integer courseId, Integer courseNumber, Integer userId, Integer type) throws Exception {
        if (courseId == null || courseNumber == null || type == null)
            return false;

        CourseSchedule campScheduleDB = courseScheduleMapper.selectByCourseId(courseId);
        if (courseNumber > campScheduleDB.getPeriods())
            throw new Exception("签到时序不可超过总课时");
        CourseSchedule campSchedule = new CourseSchedule();
        campSchedule.setId(campScheduleDB.getId());
        campSchedule.setWeek(courseNumber);
        campSchedule.setWeekly(type.toString());
        if (courseNumber.intValue() == campScheduleDB.getPeriods().intValue() && type == 0) {
            //教练签到最后一节课 并且是关闭签到时 将檬营课程变为已完成 不再更新闭营时间
//            campSchedule.setEndTime(new Date());
            CourseInfo courseInfo = courseInfoMapper.queryCourseInfoById(courseId);
            CourseInfo courseInfoDB = new CourseInfo();
            courseInfoDB.setId(courseInfo.getId());
            courseInfoDB.setStatus("5");
            courseInfoMapper.updateSelectiveById(courseInfoDB);
        }
        boolean result = courseScheduleMapper.updateSelectiveById(campSchedule) > 0;
        if (result) {
            //开启/关闭签到插入日志coach_signin_log
            CoachInfo coachInfo = coachInfoMapper.selectCoachInfoByCourseId(1, courseId);
            if (coachInfo != null) {

                CoachSigninLog coachSigninLog = new CoachSigninLog();
                coachSigninLog.setCoachId(coachInfo.getId());
                coachSigninLog.setCourseId(courseId);
                coachSigninLog.setCourseNumber(courseNumber);
                if (type == 1) {
                    //开启
                    coachSigninLog.setCourseSigninStartTime(new Date());
                    coachSigninLog.setCreatedBy(userId);
                    boolean suc = coachSigninLogMapper.insertSelective(coachSigninLog) > 0;
                    if (suc) {
                        log.info("教练开启檬营签到日志插入成功");
                    }
                }
                if (type == 0) {
                    //关闭签到
                    coachSigninLog = coachSigninLogMapper.selectOne(coachSigninLog);
                    coachSigninLog.setCourseSigninEndTime(new Date());
                    int courseSigninPersonCount = courseSignMapper.queryCoachCourseSignInCount(courseId,courseNumber, coachInfo.getMobile());
                    if (courseSigninPersonCount > 0) {
                        coachSigninLog.setCourseSigninPersonCount(courseSigninPersonCount);
                    }
                    boolean suc = coachSigninLogMapper.updateSelectiveById(coachSigninLog) > 0;
                    if (suc) {
                        log.info("教练关闭檬营签到日志插入成功");
                    }
                }
            }
        }
        return result;
    }

    /**
     *@Author: timo
     *@Date: 2018/3/27 11:23
     *@Description:
     * 添加私教日程
     * 私教教练添加日程的时候需要考虑一下几个点
     *
     * 1.同一订单同一时间段是否重复
     * 2.该教练添加的日程是总课程的第几节课程
     * 3.该教练添加的日程是该教练的第几节课程
     *
     */
    public boolean savePtCourseSign(CourseSign courseSign){

        // 新增日程
        // step 1 先查询该课程已经有那些课程没有签到得 获取最小的一个未签到得课程 安排到日程中
        CourseSign courseSignOld = courseSignMapper.queryMinSortCourseSignByCourseIdOrOrderId(courseSign.getCourseId(),courseSign.getOrderId());
        if(courseSignOld == null) return Boolean.FALSE;

        courseSignOld.setStartTime(courseSign.getStartTime());
        courseSignOld.setEndTime(courseSign.getEndTime());
        courseSignOld.setUpdatedBy(courseSign.getUpdatedBy());
        courseSignOld.setUpdatedTime(new Date());
        courseSignOld.setCoachId(courseSign.getCoachId());
        courseSignOld.setOrderId(courseSign.getOrderId());
        courseSignOld.setStoreId(courseSign.getStoreId());
        boolean addStatus = courseSignMapper.updatePrivateCourseSign(courseSignOld) > 0;
        // 发送模板消息
        templateSendService.sendPtAddCourseSignTemplateMsg(courseSignOld);
        return addStatus;
    }

    /**
     * 同一订单同一时间段内不能存在重复的日程计划
     * @Author : timo
     * @param orderId
     * @param startTime
     * @param endTime
     * @return true 存在 / false 不存在
     */
    public boolean checkScheduleRepeat(Integer orderId, Date startTime, Date endTime, Integer courseSignId){
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("orderId",orderId);
        paramMap.put("startTime",startTime);
        paramMap.put("endTime",endTime);
        paramMap.put("courseSignId",courseSignId);
        return courseSignMapper.queryCourseScheduleCountBy(paramMap) > 0;
    }

    public boolean savePlpeOrPlecCourseSign(CourseSign courseSign){

        // 日程变更
        if(courseSign.getId() != null){
            courseSign.setUpdatedTime(new Date());
            CourseSign courseSignOld = courseSignMapper.selectById(courseSign.getId());
            courseSignOld.setRemark(courseSign.getRemark());
            courseSignOld.setUpdatedTime(new Date());
            courseSignOld.setStartTime(courseSign.getStartTime());
            courseSignOld.setEndTime(courseSign.getEndTime());

            return courseSignMapper.updateById(courseSignOld) > 0;
        }

        // 新增日程
        OrderDetail orderDetail = orderDetailMapper.queryOrderDetailByOrderId(courseSign.getOrderId());
        ServicePrice servicePrice = servicePriceMapper.queryServicePriceByOrderId(courseSign.getOrderId());

        courseSign.setStoreId(orderDetail.getStoreId());
        courseSign.setUpdatedTime(new Date());
        courseSign.setCourseSortNum(1);
        courseSign.setCoachCourseSortNum(1);
        courseSign.setCourseNumber(1);
        courseSign.setCourseId(servicePrice.getCourseId());
        int addCount = courseSignMapper.insertSelective(courseSign);
        // 发送模板消息
        templateSendService.sendPtAddCourseSignTemplateMsg(courseSign);
        return addCount > 0;
    }

    /**
     *@Author: timo
     *@Date: 2018/3/30 15:56
     *@Description:
     * 添加教练便签
     *
     */
    public boolean addCoachNote(CourseSign courseSign){
        courseSign.setStatus(1);
        courseSign.setCreatedTime(new Date());
        return courseSignMapper.insertSelective(courseSign) > 0;
    }

    /**
     *@Author: timo
     *@Date: 2018/4/13 09:38
     *@Description:
     * 获取签到详情的二维码展示的状态
     * 返回值：
     * 1. 待展示 表示课程时间 未到 开始时间会提前半小时
     * 2. 显示二维码 表示当前时间在显示的时间范围内
     * 3. 已过期 表示课程时间已过 只有团课和训练营的课程才会有已过期 私教类型课程不会有
     *
     */
    public int getSignQRCodeStatus(Date startTime, Date endTime, Integer courseType){

        startTime = DateUtil.addMinites(startTime, QRCODE_MIN_OVERTIME);
        endTime = DateUtil.addMinites(endTime, QRCODE_MAX_OVERTIME);
        Date nowTime = new Date();

        // 如果未到该日程的开始时间就不显示签到二维码 提前三十分钟才显示
        if (!startTime.before(nowTime)) return 1;

        // 二维码延长半小时 这里只是限制了团课和训练营的 其余的不做限制
        if (endTime.before(nowTime) && OrderContants.OrderType.team_course.getIndex() == courseType.intValue()
                || endTime.before(nowTime) && OrderContants.OrderType.fun_camp.getIndex() == courseType.intValue()) return 3;

        return 2;
    }

}